package com.example.data.factory.service.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.data.factory.common.Dto.*;
import com.example.data.factory.common.common.StringConstant;
import com.example.data.factory.common.result.PageVO;
import com.example.data.factory.common.result.R;
import com.example.data.factory.common.util.CommonUtil;
import com.example.data.factory.entity.entity.DatabaseInfo;
import com.example.data.factory.mapper.mapper.DatabaseInfoMapper;
import com.example.data.factory.service.service.DatabaseInfoService;
import org.springframework.beans.BeanUtils;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 数据库信息 服务实现类
 * </p>
 *
 * @author lhy
 * @since 2025-03-03
 */
@Service
public class DatabaseInfoServiceImpl extends ServiceImpl<DatabaseInfoMapper, DatabaseInfo> implements DatabaseInfoService {
    @Resource
    private CommonUtil commonUtil;

    @Override
    public R<DatabaseInfo> search(SerachDataBaseDto serachDataBaseDtoc) {
        Page<DatabaseInfo> page = new Page<> ( serachDataBaseDtoc.getPageNumber (), serachDataBaseDtoc.getPageSize () );
        // 构建查询条件
        LambdaQueryWrapper<DatabaseInfo> wrapper = new LambdaQueryWrapper<> ();

        if (Objects.nonNull ( serachDataBaseDtoc.getStatus () )) {
            wrapper.eq ( DatabaseInfo::getStatus, serachDataBaseDtoc.getStatus () );
        }
        if (StringUtils.isNotBlank ( serachDataBaseDtoc.getName () )) {
            wrapper.like ( DatabaseInfo::getName, serachDataBaseDtoc.getName () );
        }
        wrapper.eq ( DatabaseInfo::getDeleted, 0 ); // 确保未删除的数据
        Page<DatabaseInfo> page1 = this.page ( page, wrapper );
        PageVO<DatabaseInfo> pageVO = new PageVO<> ();
        BeanUtil.copyProperties ( page1, pageVO );
        return R.Success ( pageVO );
    }

    @Override
    public R<DatabaseInfo> insert(InsertDataBaseDto insertDataBaseDto, HttpServletRequest request) {
        DatabaseInfo databaseInfo = new DatabaseInfo ();
        BeanUtils.copyProperties ( insertDataBaseDto, databaseInfo );
        String username = commonUtil.extractUsernameFromRequest ( request );
        databaseInfo.setCreateBy ( username );
        databaseInfo.setCreateTime ( LocalDateTime.now () );
        databaseInfo.setUpdateTime ( LocalDateTime.now () );
        //获取所有的数据库信息
        List<DatabaseInfo> list = this.list ();
        if (list.stream ().anyMatch ( data -> data.getName ().equals ( insertDataBaseDto.getName () ) ) || list.stream ().anyMatch ( data -> data.getUrl ().equals ( insertDataBaseDto.getUrl () ) )) {
            return R.Failed ( "数据源名称或者连接信息重复，请重新进行输入" );
        }
        boolean save = this.save ( databaseInfo );
        if (save) {
            return R.Success ( StringConstant.INSERTSUCCESS );
        } else {
            return R.Failed ( StringConstant.INSERTFAILD );
        }
    }

    @Override
    public R<DatabaseInfo> updates(UpdateDataBaseDto updateDataBaseDto) {
        DatabaseInfo one = this.getOne ( new LambdaQueryWrapper<DatabaseInfo> ().eq ( DatabaseInfo::getId, updateDataBaseDto.getId () ) );
        if (one == null) {
            return R.Failed ( "数据不存在" );
        }
        if (one.getStatus () == 1 || one.getStatus () == 2) {
            return R.Failed ( "数据已发布或者已停用，无法进行修改" );
        }
        List<DatabaseInfo> list = this.list ();
        if (list.stream ().anyMatch ( data -> data.getName ().equals ( updateDataBaseDto.getName () ) ) || list.stream ().anyMatch ( data -> data.getUrl ().equals ( updateDataBaseDto.getUrl () ) )) {
            return R.Failed ( "数据库名称或者连接信息已存在，无法进行修改" );
        }
        DatabaseInfo databaseInfo = new DatabaseInfo ();
        databaseInfo.setUpdateTime ( LocalDateTime.now () );
        boolean update = this.update ( new LambdaUpdateWrapper<DatabaseInfo> ().set ( DatabaseInfo::getType, updateDataBaseDto.getType () )
                .set ( DatabaseInfo::getName, updateDataBaseDto.getName () )
                .set ( DatabaseInfo::getDescription, updateDataBaseDto.getDescription () )
                .set ( DatabaseInfo::getUrl, updateDataBaseDto.getUrl () )
                .set ( DatabaseInfo::getUsername, updateDataBaseDto.getUsername () )
                .set ( DatabaseInfo::getPassword, updateDataBaseDto.getPassword () )
                .eq ( DatabaseInfo::getId, updateDataBaseDto.getId () ) );
        if (update) {
            return R.Success ( StringConstant.UPDATESUCCESS );
        } else {
            return R.Failed ( StringConstant.UPDATEFAILED );
        }

    }

    @Override
    public R<DatabaseInfo> updatestatus(UpdateDataBaseStatus updateDataBaseStatus) {
        DatabaseInfo one = this.getOne ( new LambdaQueryWrapper<DatabaseInfo> ().eq ( DatabaseInfo::getId, updateDataBaseStatus.getId () ) );
        if (one.getDeleted () == 1) {
            return R.Failed ( "该数据已删除" );
        }
        DatabaseInfo databaseInfo = new DatabaseInfo ();
        databaseInfo.setUpdateTime ( LocalDateTime.now () );
        boolean update = this.update ( new LambdaUpdateWrapper<DatabaseInfo> ().set ( DatabaseInfo::getStatus, updateDataBaseStatus.getStatus () )
                .eq ( DatabaseInfo::getId, updateDataBaseStatus.getId () ) );
        if (update) {
            return R.Success ( StringConstant.UPDATESUCCESS );
        }
        return R.Failed ( StringConstant.UPDATEFAILED );
    }

    @Override
    public R<DatabaseInfo> deletes(DeleteDataBaseDto deleteDataBaseDto) {
        // 使用提供的ID查找对应的DatabaseInfo对象
        DatabaseInfo one = this.getOne ( new LambdaQueryWrapper<DatabaseInfo> ().eq ( DatabaseInfo::getId, deleteDataBaseDto.getId () ) );

        // 如果找不到该对象，则返回失败信息
        if (one == null) {
            return R.Failed ( "找不到可用的数据源" );
        }

        // 检查状态是否允许删除
        if (one.getStatus () == 1 || one.getStatus () == 2) {
            return R.Failed ( "只有未发布的状态可以删除" );
        }

        // 在找到的对象上设置deleted标志
        one.setDeleted ( (byte) 1 );

        // 更新数据库中的记录
        boolean updateResult = this.updateById ( one );

        // 根据更新结果返回相应的响应
        if (updateResult) {
            return R.Success ( StringConstant.UPDATESUCCESS );
        } else {
            return R.Failed ( StringConstant.UPDATEFAIL );
        }
    }

    public R<String> testDatabaseConnection(DataBaseConnectDto connectionDto) {
        // 从前端接收的连接信息
        String url = connectionDto.getUrl ();
        String username = connectionDto.getUsername ();
        String password = connectionDto.getPassword ();
        String type = connectionDto.getType (); // 假设这里有数据库类型的信息
        // 创建数据源
        DataSource dataSource = createDataSource ( url, username, password, type );

        try (Connection connection = dataSource.getConnection ()) {
            // 如果能到这里说明连接成功
            return R.Success ( "成功连接到数据库" );
        } catch (SQLException e) {
            // 处理SQL异常
            if (e.getMessage ().contains ( "Unknown database" )) {
                // 数据库不存在的情况
                return R.Success ( "指定的数据库不存在，但服务器连接成功", 200 );
            } else {
                // 其他类型的SQL异常，如认证失败等
                return R.Failed ( "连接数据库失败" );
            }
        }
    }

    private DataSource createDataSource(String url, String username, String password, String type) {
        DriverManagerDataSource dataSource = new DriverManagerDataSource ();
        dataSource.setDriverClassName ( getDriverClassName ( type ) ); // 设置驱动类名
        dataSource.setUrl ( url );
        dataSource.setUsername ( username );
        dataSource.setPassword ( password );

        return dataSource;
    }

    private String getDriverClassName(String type) {
        switch (type.toLowerCase ()) {
            case "mysql":
                return "com.mysql.cj.jdbc.Driver";
            // 可以添加更多数据库类型的支持
            default:
                throw new IllegalArgumentException ( "不支持的数据库类型: " + type );
        }
    }
}
